Cómo compartir datos entre aplicaciones
Este artículo se publicó anteriormente con el
número E11029
ResumenEn muchas ocasiones es necesario comunicar diferentes aplicaciones entre sí mediante la compartición de datos. Este artículo discute la utilización de secciones para que aplicaciones que se ejecutan en procesos diferentes puedan comunicarse mutuamente. Más informaciónLa arquitectura Windows proporciona un conjunto de mecanismos que permiten la comunicación entre diferentes procesos. Entre estos mecanismos se encuentran los siguientes: - Ole Automation, DCOM. - WinSockets. - Ficheros mapeados en memoria, Secciones. - NamedPipes. - MailSlots. - DDE, NetDDE. - NetBios. - Paso de mensajes. - RPCs. - etc. Cada método es útil en función del tipo de compartición que se quiera realizar. Hay que tener en cuenta si los procesos se van a ejecutar en equipos diferentes o en el mismo equipo, si se busca la rapidez en la comunicación, si el mecanismo está disponible en todas las plataformas, etc. En este artículo se ha considerado oportuno hablar sobre la compartición de datos mediante secciones, ya que es un método sencillo y que posee las siguientes características: - Es el más rápido, ya que se utiliza la memoria como medio de comunicación. - Existe en las plataformas de 32 bits: Windows NT, Windows 95, Windows 98, Windows CE, etc. - Permite la comunicación entre procesos en el mismo equipo. Al utilizar la memoria como medio de compartición de datos, los procesos no pueden residir en equipos diferentes. Las secciones son un subconjunto de un mecanismo denominado "filemapping" o "ficheros mapeados en memoria". El filemapping permite que aplicaciones diferentes utilicen los mismos ficheros de forma concurrente. La función de la API de 32 bits que implementa esta característica es: Declare Function CreateFileMapping Lib "kernel32" Alias _ "CreateFileMappingA" (ByVal hFile As Long, _ lpFileMappigAttributes As Any, ByVal flProtect As Long, _ ByVal dwMaximumSizeHigh As Long, ByVal dwMaximumSizeLow As _ Long, ByVal lpName As String) As Long Afortunadamente, en el primer parámetro de CreateFileMapping se le puede indicar el valor &HFFFFFFFF , con lo que el fichero se crearía en el fichero de swapping (pagefile.sys) y, por tanto, se mapearía a memoria. De esta forma, se consigue crear una sección. Adicionalmente, hay que llamar a la función: Declare Function MapViewOfFile Lib "kernel32" (ByVal _ hFileMappingObject As Long, ByVal dwDesiredAccess As Long, _ ByVal dwFileOffsetHigh As Long, ByVal dwFileOffsetLow As _ Long, ByVal dwNumberOfBytesToMap As Long) As Long para que se produzca el mapeo de forma inmediata. Esta función devuelve un Long que es un puntero a la zona de memoria donde se realiza el mapeo. Este puntero es fácil de utilizar desde lenguajes como Visual C++, pero no es adecuado para Visual Basic. Para salvar esta incoveniencia hay que hacer uso de la función CopyMemory, que permite leer el contenido de una dirección de memoria y almacenarlo en una variable. En este artículo se presenta un ejemplo de cómo dos aplicaciones pueden compartir una variable de tipo Long. Se advierte que el acceso a datos compartidos requiere la utilización de mecanismos que eviten condiciones de carrera o interbloqueos. Por simplicidad, en el ejemplo no se ha tenido en cuenta esta problemática por lo que se recomienda que se utilice con cuidado. Se recomienda asimismo la lectura del artículo de la base de datos de conocimientos de Microsoft: ARTICLE-ID: 551080 (http://support.microsoft.com/kb/551080/ES/) TITLE : Cómo controlar el acceso concurrente a datos compartidos En dicho artículo se explica cómo compartir datos con la seguridad de que el acceso a los datos por varios procesos se va a realizar de forma correcta. PASOS PARA PROBAR EL EJEMPLO ---------------------------- 1. Cree un nuevo proyecto con un formulario (.frm) y un módulo de código (.bas) 2. En el formulario cree dos botones y una caja de texto con las siguientes propiedades: Command1 Name: btnValor Caption: Cambiar Valor Command2 Name: btnMostrarValor Caption: Mostrar Valor Text1 Name: txtValor 3. Escriba el siguiente código en el módulo .bas: Declare Function CreateFileMapping Lib "kernel32" Alias _ "CreateFileMappingA" (ByVal hFile As Long, _ lpFileMappigAttributes As Any, ByVal flProtect As Long, _ ByVal dwMaximumSizeHigh As Long, ByVal _ dwMaximumSizeLow As Long, ByVal lpName As String) As Long Declare Function MapViewOfFile Lib "kernel32" (ByVal _ hFileMappingObject As Long, ByVal dwDesiredAccess As _ Long, ByVal dwFileOffsetHigh As Long, ByVal dwFileOffsetLow _ As Long, ByVal dwNumberOfBytesToMap As Long) As Long Declare Function CloseHandle Lib "kernel32" (ByVal hObject As _ Long) As Long Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (lpDestination As Any, lpSource As Any, ByVal dwLength As Long) Public Const PAGE_READWRITE = 4 Public Const STANDARD_RIGHTS_REQUIRED = &HF0000 Public Const SECTION_EXTEND_SIZE = &H10 Public Const SECTION_MAP_EXECUTE = &H8 Public Const SECTION_MAP_READ = &H4 Public Const SECTION_MAP_WRITE = &H2 Public Const SECTION_QUERY = &H1 Public Const SECTION_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED Or _ SECTION_QUERY Or SECTION_MAP_WRITE Or SECTION_MAP_READ Or _ SECTION_MAP_EXECUTE Or SECTION_EXTEND_SIZE Public Const FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS 4. Copie el siguiente código en el formulario: Dim lPunteroDato As Long 'Puntero a memoria con el valor del dato Dim lValorDato As Long 'Variable auxiliar para mostrar el valor en 'memoria Dim hSection As Long 'Manejador de la sección Private Sub btnMostrarValor_Click() If lPunteroDato Then ' Copiamos el contenido de la memoria apuntada por ' lPunteroDato a la variable auxiliar lValorDato CopyMemory lValorDato, ByVal (lPunteroDato), _ Len(lValorDato) MsgBox lValorDato End If End Sub Private Sub btnValor_Click() If lPunteroDato Then lValorDato = Val(txtValor) ' Copiamos el contenido de la variable auxiliar lValorDato ' a la dirección de memoria lPunteroDato CopyMemory ByVal (lPunteroDato), lValorDato, _ Len(lValorDato) End If End Sub Private Sub Form_Load() ' Creamos fichero mapeado en memoria hSection = CreateFileMapping(&HFFFFFFFF, ByVal (0&), _ PAGE_READWRITE, 0, Len(lValorDato), "miseccion") ' Creamos la sección If (hSection) Then lPunteroDato = MapViewOfFile(hSection, _ FILE_MAP_ALL_ACCESS, 0,_0, 0) Else MsgBox "Fallo al crear fichero mapeado en memoria" Unload Me End If End Sub Private Sub Form_Unload(Cancel As Integer) ' Cerramos todos los handles abiertos If lPunteroDato Then UnmapViewOfFile (lPunteroDato) If hSection Then CloseHandle (hSection) End Sub 5. Compile la aplicación. 6. Para probar el código ejecute desde el explorador de Windows dos instancias de la misma aplicación. En la caja de texto del formulario introduzca un entero largo y pulse el botón "Cambiar Valor" o "Mostrar Valor". Podrá comprobar como las modificaciones producidas por una aplicación pueden ser vistas por la otra. ReferenciasLa información de este artículo se refiere a:
|
Buscar en
|
Volver
al principio
